package com.edu.exam.entity.grading.analysis;

import com.edu.exam.enums.grading.analysis.DistributionType;
import com.edu.exam.enums.grading.StatisticalMethod;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 统计数据实体类
 * 所属模块：E-03 成绩分析模块
 *
 * <p>统计数据实体用于存储和管理描述性统计分析结果，包含
 * 基础统计指标、分布特征、四分位数等信息。支持完整的描述性统计分析。</p>
 *
 * <p>核心功能：
 * - 基础统计：均值、中位数、众数、标准差等
 * - 分布特征：偏度、峰度、极差等分布特征
 * - 分位数：四分位数、百分位数等位置统计
 * - 数据验证：统计数据的合理性和完整性检查
 * - 计算衍生：基于基础统计计算衍生指标</p>
 *
 * @author 系统生成
 * @version 1.0
 * @since 2025-11-10
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class StatisticsData {

    /**
     * 统计数据唯一标识
     */
    @Id
    @Column(name = "statistics_id", length = 64)
    private String statisticsId;

    /**
     * 关联结果ID
     *
     * <p>对应的分析结果ID。</p>
     */
    @Column(name = "result_id", nullable = false, length = 64)
    private String resultId;

    /**
     * 数据范围
     *
     * <p>统计数据的数据范围描述。</p>
     */
    @Column(name = "data_scope", columnDefinition = "TEXT")
    private String dataScope;

    /**
     * 均值
     *
     * <p>数据的算术平均值。</p>
     */
    @Column(name = "mean_value", precision = 10, scale = 2)
    private BigDecimal meanValue;

    /**
     * 中位数
     *
     * <p>数据的中位数。</p>
     */
    @Column(name = "median_value", precision = 10, scale = 2)
    private BigDecimal medianValue;

    /**
     * 众数
     *
     * <p>数据的众数（出现频率最高的值）。</p>
     */
    @Column(name = "mode_value", precision = 10, scale = 2)
    private BigDecimal modeValue;

    /**
     * 标准差
     *
     * <p>数据的标准差。</p>
     */
    @Column(name = "standard_deviation", precision = 10, scale = 2)
    private BigDecimal standardDeviation;

    /**
     * 方差
     *
     * <p>数据的方差。</p>
     */
    @Column(name = "variance", precision = 10, scale = 2)
    private BigDecimal variance;

    /**
     * 最小值
     *
     * <p>数据的最小值。</p>
     */
    @Column(name = "minimum_value", precision = 10, scale = 2)
    private BigDecimal minimumValue;

    /**
     * 最大值
     *
     * <p>数据的最大值。</p>
     */
    @Column(name = "maximum_value", precision = 10, scale = 2)
    private BigDecimal maximumValue;

    /**
     * 极差
     *
     * <p>最大值与最小值的差值。</p>
     */
    @Column(name = "range_value", precision = 10, scale = 2)
    private BigDecimal rangeValue;

    /**
     * 第一四分位数（Q1）
     *
     * <p>数据的25%分位数。</p>
     */
    @Column(name = "q1_value", precision = 10, scale = 2)
    private BigDecimal q1Value;

    /**
     * 第二四分位数（Q2）
     *
     * <p>数据的50%分位数（即中位数）。</p>
     */
    @Column(name = "q2_value", precision = 10, scale = 2)
    private BigDecimal q2Value;

    /**
     * 第三四分位数（Q3）
     *
     * <p>数据的75%分位数。</p>
     */
    @Column(name = "q3_value", precision = 10, scale = 2)
    private BigDecimal q3Value;

    /**
     * 四分位距（IQR）
     *
     * <p>Q3与Q1的差值。</p>
     */
    @Column(name = "iqr_value", precision = 10, scale = 2)
    private BigDecimal iqrValue;

    /**
     * 偏度
     *
     * <p>数据分布的偏度系数。</p>
     */
    @Column(name = "skewness", precision = 10, scale = 4)
    private BigDecimal skewness;

    /**
     * 峰度
     *
     * <p>数据分布的峰度系数。</p>
     */
    @Column(name = "kurtosis", precision = 10, scale = 4)
    private BigDecimal kurtosis;

    /**
     * 样本数量
     *
     * <p>参与统计的样本数量。</p>
     */
    @Column(name = "sample_count")
    private Integer sampleCount = 0;

    /**
     * 有效样本数量
     *
     * <p>有效（非空、非异常）的样本数量。</p>
     */
    @Column(name = "valid_sample_count")
    private Integer validSampleCount = 0;

    /**
     * 缺失值数量
     *
     * <p>缺失值的数量。</p>
     */
    @Column(name = "missing_count")
    private Integer missingCount = 0;

    /**
     * 异常值数量
     *
     * <p>异常值的数量。</p>
     */
    @Column(name = "outlier_count")
    private Integer outlierCount = 0;

    /**
     * 变异系数
     *
     * <p>标准差与均值的比值。</p>
     */
    @Column(name = "coefficient_of_variation", precision = 8, scale = 4)
    private BigDecimal coefficientOfVariation;

    /**
     * 标准误
     *
     * <p>均值的标准误。</p>
     */
    @Column(name = "standard_error", precision = 10, scale = 4)
    private BigDecimal standardError;

    /**
     * 95%置信区间下界
     *
     * <p>均值95%置信区间的下界。</p>
     */
    @Column(name = "confidence_interval_lower", precision = 10, scale = 2)
    private BigDecimal confidenceIntervalLower;

    /**
     * 95%置信区间上界
     *
     * <p>均值95%置信区间的上界。</p>
     */
    @Column(name = "confidence_interval_upper", precision = 10, scale = 2)
    private BigDecimal confidenceIntervalUpper;

    /**
     * 数据分布类型
     *
     * <p>数据的分布类型判断。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "distribution_type", length = 20)
    private DistributionType distributionType;

    /**
     * 正态性检验统计量
     *
     * <p>正态性检验的统计量值。</p>
     */
    @Column(name = "normality_statistic", precision = 10, scale = 4)
    private BigDecimal normalityStatistic;

    /**
     * 正态性检验p值
     *
     * <p>正态性检验的p值。</p>
     */
    @Column(name = "normality_p_value", precision = 10, scale = 6)
    private BigDecimal normalityPValue;

    /**
     * 是否正态分布
     *
     * <p>根据正态性检验结果判断是否为正态分布。</p>
     */
    @Column(name = "is_normal_distribution")
    private Boolean isNormalDistribution;

    /**
     * 统计方法
     *
     * <p>使用的统计计算方法。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "statistical_method", length = 20)
    private StatisticalMethod statisticalMethod;

    /**
     * 置信水平
     *
     * <p>统计推断的置信水平。</p>
     */
    @Column(name = "confidence_level", precision = 3, scale = 2)
    private BigDecimal confidenceLevel;

    /**
     * 显著性水平
     *
     * <p>假设检验的显著性水平。</p>
     */
    @Column(name = "significance_level", precision = 3, scale = 3)
    private BigDecimal significanceLevel;

    /**
     * 百分位数
     *
     * <p>JSON格式的百分位数数据。</p>
     */
    @Column(name = "percentiles", columnDefinition = "TEXT")
    private String percentiles;

    /**
     * 频率分布
     *
     * <p>JSON格式的频率分布数据。</p>
     */
    @Column(name = "frequency_distribution", columnDefinition = "TEXT")
    private String frequencyDistribution;

    /**
     * 统计备注
     *
     * <p>统计计算的备注信息。</p>
     */
    @Column(name = "statistical_notes", columnDefinition = "TEXT")
    private String statisticalNotes;

    /**
     * 计算参数
     *
     * <p>JSON格式的计算参数配置。</p>
     */
    @Column(name = "calculation_parameters", columnDefinition = "TEXT")
    private String calculationParameters;

    /**
     * 计算耗时
     *
     * <p>统计计算的耗时（毫秒）。</p>
     */
    @Column(name = "calculation_duration")
    private Long calculationDuration;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;



    // ===== 数据访问方法 =====

    /**
     * 设置基础统计指标
     *
     * @param mean 均值
     * @param median 中位数
     * @param mode 众数
     * @param sd 标准差
     * @param min 最小值
     * @param max 最大值
     */
    public void setBasicStatistics(BigDecimal mean, BigDecimal median, BigDecimal mode,
                                  BigDecimal sd, BigDecimal min, BigDecimal max) {
        this.meanValue = mean;
        this.medianValue = median;
        this.modeValue = mode;
        this.standardDeviation = sd;
        this.minimumValue = min;
        this.maximumValue = max;
    }

    /**
     * 设置四分位数
     *
     * @param q1 第一四分位数
     * @param q2 第二四分位数（中位数）
     * @param q3 第三四分位数
     */
    public void setQuartiles(BigDecimal q1, BigDecimal q2, BigDecimal q3) {
        this.q1Value = q1;
        this.q2Value = q2;
        this.q3Value = q3;
        this.medianValue = q2;
    }

    /**
     * 设置分布特征
     *
     * @param skewness 偏度
     * @param kurtosis 峰度
     * @param distributionType 分布类型
     */
    public void setDistributionCharacteristics(BigDecimal skewness, BigDecimal kurtosis,
                                             DistributionType distributionType) {
        this.skewness = skewness;
        this.kurtosis = kurtosis;
        this.distributionType = distributionType;
    }

    /**
     * 设置正态性检验结果
     *
     * @param statistic 检验统计量
     * @param pValue p值
     * @param isNormal 是否正态分布
     */
    public void setNormalityTest(BigDecimal statistic, BigDecimal pValue, Boolean isNormal) {
        this.normalityStatistic = statistic;
        this.normalityPValue = pValue;
        this.isNormalDistribution = isNormal;
    }

    /**
     * 设置样本信息
     *
     * @param total 总样本数
     * @param valid 有效样本数
     * @param missing 缺失值数
     * @param outlier 异常值数
     */
    public void setSampleInfo(Integer total, Integer valid, Integer missing, Integer outlier) {
        this.sampleCount = total;
        this.validSampleCount = valid;
        this.missingCount = missing;
        this.outlierCount = outlier;
    }

    /**
     * 检查统计数据的合理性
     *
     * @return 如果数据合理返回true，否则返回false
     */
    public boolean isValidStatistics() {
        // 检查基本约束
        if (sampleCount != null && sampleCount < 0) return false;
        if (validSampleCount != null && validSampleCount < 0) return false;
        if (missingCount != null && missingCount < 0) return false;
        if (outlierCount != null && outlierCount < 0) return false;

        // 检查数值范围
        if (minimumValue != null && maximumValue != null &&
            minimumValue.compareTo(maximumValue) > 0) return false;

        if (q1Value != null && q2Value != null && q3Value != null) {
            if (q1Value.compareTo(q2Value) > 0 || q2Value.compareTo(q3Value) > 0) return false;
        }

        // 检查标准差和方差的一致性
        if (standardDeviation != null && variance != null) {
            BigDecimal expectedVariance = standardDeviation.pow(2);
            if (variance.compareTo(expectedVariance.subtract(BigDecimal.valueOf(0.01))) < 0 ||
                variance.compareTo(expectedVariance.add(BigDecimal.valueOf(0.01))) > 0) {
                return false;
            }
        }

        // 检查正态性检验p值
        if (normalityPValue != null &&
            (normalityPValue.compareTo(BigDecimal.ZERO) < 0 ||
             normalityPValue.compareTo(BigDecimal.ONE) > 0)) {
            return false;
        }

        return true;
    }

    // ===== 数据访问方法 =====

  }